﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using GeoSketch2.Core;

namespace GeoSketch2.Archaeo
{
    /// <summary>
    /// The excavation site object, there should be only one site per project
    /// site has squares as sub-section, and squares have unit as sub-section
    /// </summary>
    public class _ExcavationSite : BaseExcavationArea
    {
        #region Fields
        /// <summary>
        /// The squares composing the whole site
        /// </summary>
        public List<ExcavationSquare> ExcavationSquares;

        #endregion

        #region Constructor
        /// <summary>
        /// The excavation site object, there should be only one site per project
        /// site has squares as sub-section, and squares have unit as sub-section
        /// </summary>
        public ExcavationSite(ArchaeoProject Project)
            : this("Main Site",Project)
        {

        }

        /// <summary>
        /// The excavation site object, there should be only one site per project
        /// site has squares as sub-section, and squares have unit as sub-section
        /// </summary>
        /// <param name="Name">The name of the excavation area</param>
        public ExcavationSite(string Name, ArchaeoProject Project)
            :this(Name,DateTime.Now,"",DefaultSiteBounds,new List<Layer>(),Project)
        {
                      
        }

        /// <summary>
        /// The excavation site object, there should be only one site per project
        /// site has squares as sub-section, and squares have unit as sub-section
        /// </summary>
        /// <param name="Name">The name of the excavation area</param>
        /// <param name="ArchaeologistName">The name of the archaeologist</param>
        /// <param name="CreationTime">The time of creation</param>
        /// <param name="Bounds">The bounds of the area in object coordinates, Y-axis upside</param>
        /// <param name="AvailableLayers">The available layers from this area</param>
        /// <param name="LineTypeLibrary">The list of all available linetypes for the project</param>
        /// <param name="ProjectLayers">All layers of the project</param>
        /// <param name="ArchaeologistsList">The list of the archaeologists</param>
        /// <param name="Layer0">The layer0 of the Site, this Layer is always present when creating a new square or unit</param>
        public ExcavationSite(string Name, DateTime CreationTime, string ArchaeologistName, Point2D64D[] Bounds,List<Layer> AvailableLayers,ArchaeoProject Project)
            :base(Name,ArchaeologistName,CreationTime,Bounds,AvailableLayers,Project)
        {
            this.ExcavationSquares = new List<ExcavationSquare>();
            this.AvailableLayers.Add(Project.Layer0);
        }
        #endregion

        #region Methods
        /// <summary>
        /// The method used if the area has something to draw, which is not a geo object
        /// </summary>
        /// <param name="Viewport">The viewport the area will draw to</param>
        public override void Draw(Viewport Viewport)
        {
            foreach (ExcavationSquare s in ExcavationSquares)
            {
                PointF[] bounds_screen_coordinates = Viewport.Object2ImageTransformation.TransformF(s.Bounds);
                GraphicsPath path = new GraphicsPath(bounds_screen_coordinates, Tools.GetPathPointsType(bounds_screen_coordinates.Length));
                Viewport.Graphic.DrawPath(Vars.Setup.StandardObjects.ExcavationAreas.ExcavationSite.ExcavationSquaresDisplayPen, path);

                Point2D64D BoundsCentroid = s.Bounds.GetCentroid();
                BoundsCentroid = Viewport.Object2ImageTransformation.Transform(BoundsCentroid);
                SizeF StringSize = Viewport.Graphic.MeasureString(s.Name, Vars.Setup.StandardObjects.ExcavationAreas.ExcavationSite.NameFontdisplay);
                BoundsCentroid.X -= StringSize.Width / 2;
                BoundsCentroid.Y -= StringSize.Height / 2;
                Viewport.Graphic.DrawString(s.Name, Vars.Setup.StandardObjects.ExcavationAreas.ExcavationSite.NameFontdisplay, Vars.Setup.StandardObjects.ExcavationAreas.ExcavationSite.ExcavationSquaresDisplayPen.Brush, BoundsCentroid);
            }
        }

        /// <summary>
        /// Gets a benchmark from its name
        /// </summary>
        public Benchmark GetBenchmarkFromName(string name)
        {
            foreach (Benchmark bm in Project.SiteBenchmarks)
            {
                if (bm.Name == name)
                {
                    return bm;
                }
            }
            return null;
        }

        /// <summary>
        /// Saves the site to a file
        /// </summary>
        public void SaveToGSK(string Filename)
        {
            FileIO.WriteGSK(this.Project, Filename);
        }

        /// <summary>
        /// Gets an excavation unit from its name
        /// </summary>
        public ExcavationUnit GetExcavationUnitFromName(string name)
        {
            foreach (ExcavationSquare s in ExcavationSquares)
            {
                foreach (ExcavationUnit u in s.ExcavationUnits)
                {
                    if (u.Name == name)
                    {
                        return u;
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// Gets a Layer from its name
        /// </summary>
        public Layer GetLayerFromName(string name)
        {
            return this.Project.ProjectLayers.Find(delegate(Layer l) { return l.Name == name; });
        }

        /// <summary>
        /// Gets a linetype from its id
        /// </summary>
        public LineType GetLineTypeFromId(int id)
        {
            return this.Project.LineTypeLibrary.Find(delegate(LineType lt) { return lt.Id == id; });
        }
        #endregion

        #region Properties
        /// <summary>
        /// The digging heigt of the site, is the sum of all digging height of every squares
        /// </summary>
        public override DiggingHeight DiggingHeight
        {
            get
            {
                DiggingHeight dst = new DiggingHeight();

                foreach (ExcavationSquare s in ExcavationSquares)
                {
                    dst.MaxHeight = Math.Max(dst.MaxHeight, s.DiggingHeight.MaxHeight);
                    dst.MinHeight = Math.Max(dst.MinHeight, s.DiggingHeight.MinHeight);
                }

                return dst;
            }
        }

        /// <summary>
        /// Gets the treeview node of the area
        /// </summary>
        public override TreeNode TreeViewNode
        {
            get
            {
                TreeNode node = new TreeNode(Name, Vars.Setup.Forms.DrawingForm.TreeViewSiteImageIndex, Vars.Setup.Forms.DrawingForm.TreeViewSiteImageIndex);
                node.Tag = this;

                foreach (ExcavationSquare square in ExcavationSquares)
                {
                    node.Nodes.Add(square.TreeViewNode);
                }

                return node;
            }
        }

        /// <summary>
        /// Gets the path of the area, the path from the main excavation site
        /// </summary>
        public override string Path
        {
            get
            {
                return Name;
            }
        }

        /// <summary>
        /// Gets the default bounds of a new site
        /// </summary>
        public static Point2D64D[] DefaultSiteBounds
        {
            get
            {
                return new Point2D64D[]{
            new Point2D64D(-1000,-1000),
            new Point2D64D(-1000,1000),
            new Point2D64D(1000,1000),
            new Point2D64D(1000,-1000)};
            }
        }

        

        /// <summary>
        /// Gets the survey logbooks of the site
        /// </summary>
        public List<SurveyLogBook> SurveyLogBooks
        {
            get
            {
                List<SurveyLogBook> dst = new List<SurveyLogBook>();

                foreach (ExcavationSquare s in ExcavationSquares)
                {
                    foreach (ExcavationUnit u in s.ExcavationUnits)
                    {
                        dst.Add(u.SurveyLogBook);
                    }
                }

                return dst;
            }
        }
        #endregion
    }
}
